﻿#include <QCoreApplication>
#include <iostream>
#include <QTextStream>
#include <QRegExp>
using namespace std;

QString encrypt(QString plainText,QString key);
QString decrypt(QString cipherText,QString key);

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QTextStream in(stdin);
    QTextStream out(stdout);
    QList<QString> strs;
    QString input="";
    QString cipher="";
    QString plain="";

    while(1)
    {
        cout<<"*****************************************字符串的加密解密********************************************"<<endl;
        cout<<endl;
        cout<<"请输入明文和密钥（以任意长的空格分隔，按回车键结束输入）："<<endl;
        input=in.readLine();     //读取输入的一行
        strs=input.split(" ",QString::SkipEmptyParts);     //按空格分割字符串
        cout<<endl;

        if(strs.size()!=2)
        {
            cout<<"输入有误，请重新输入！"<<endl;
            system("pause");
            system("cls");
            continue;
        }

        QString cipher=encrypt(strs[0],strs[1]);
        out<<"cipher:"<<cipher<<endl;

        cout<<endl;
        cout<<"请输入密文和密钥（以任意长的空格分隔，按回车键结束输入）："<<endl;
        input=in.readLine();     //读取输入的一行
        strs=input.split(" ",QString::SkipEmptyParts);     //按空格分割字符串
        cout<<endl;

        if(strs.size()!=2)
        {
            cout<<"输入有误，请重新输入！"<<endl;
            system("pause");
            system("cls");
            continue;
        }

        QString plain=decrypt(strs[0],strs[1]);
        out<<"plain:"<<plain<<endl;
        cout<<endl;

        system("pause");
        system("cls");
    }

    return a.exec();
}

QString encrypt(QString plainText,QString key)
{
    int ascii=-1;
    for(int i=0;i<plainText.size();++i)
    {
        //将明文的每一个字符的ASCII码加上key的长度重新赋给该字符
        ascii=plainText[i].toLatin1()+key.size();
        if(ascii<127)
        {
            plainText[i]=ascii;
        }else {
            //如果加起来后ASCII码已经超过127，则不进行加法
            plainText.insert(i,"!");
            ++i;
        }
    }

    //将key的每一个字符的ASCII码加1，重新赋给该字符
    for(int i=0;i<key.size();++i)
    {
        if(key[i].toLatin1()<127)
        {
            key[i]=key[i].toLatin1()+1;
        }
    }

    //密文的组成：key的长度+key开始的标志k+加密后的key+加密后的明文
    plainText=QString::number(key.size())+"k"+key+plainText;

    return plainText;
}

QString decrypt(QString cipherText,QString key)
{
    //正则表达式用于匹配key开始的标志k
    QRegExp rx("\\D+");
    int keyStart=rx.indexIn(cipherText);

    //提取原本key的长度
    int keySize=cipherText.left(keyStart).toInt();

    //验证key长度是否相等
    if(keySize==key.size())
    {
        for(int i=0;i<key.size();++i)
        {
            //验证key是否匹配
            if((cipherText[keyStart+1+i].toLatin1()-1)!=key[i].toLatin1())
            {
                return "The cipher and key do not match!";
            }
        }

        //将key前缀去掉，留下有用信息
        cipherText.remove(0,(keyStart+1+key.size()));

        //逆过程解密文
        for(int i=0;i<cipherText.size();++i)
        {
            if(cipherText[i]=='!')
            {
                cipherText.remove(i,1);
            }else {
                cipherText[i]=cipherText[i].toLatin1()-key.size();
            }
        }
        return cipherText;

    }else {
        return "The cipher and key do not match!";
    }

}
